﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.Data;

using agvcontroller.Common;
using agvcontroller.Log;
using agvcontroller.Common.DataBase;
using agvcsimulator.Driver;

namespace agvcsimulator.Module
{
    public delegate void deleReportPositionSim(object sender, int nodeNo);
    public delegate void deleReportConnectionSim(object sender, enumConnect connect);
    public delegate void deleReportOperationSim(object sender, enumOperation operation);
    public delegate void deleReportCommunicationSim(object sender, enumCommnication communication);
    public delegate void deleReportAlarmSim(object sender, int alarmId);
    public delegate void deleAcceptCommandSim(object sender, string vehiclejobId);
    public delegate void deleRejectCommandSim(object sender, string vehiclejobId);
    public delegate void deleCommandCompletedSim(object sender, string vehiclejobId);
    public delegate void deleRequestRouteSim(object sender, int cmdId);
    public delegate void deleReportVehicleInfoSim(object sender, stVehicleInfo info);
    public delegate void deleReportInterlockSignalSim(object sender, List<int> interlock);
    public delegate void deleOnRcvMsgSim(object sender, string msg);
    public delegate void deleOnSendMsgSim(object sender, string msg);

    public class CVehicleSim
    {
        #region event
        public event deleReportPositionSim onReportPosition;
        public event deleReportConnectionSim onReportConnection;
        public event deleReportCommunicationSim onReportCommunication;
        public event deleReportOperationSim onReportOperation;
        public event deleReportAlarmSim onReportAlarm;
        public event deleAcceptCommandSim onAcceptCommand;
        public event deleRejectCommandSim onRejectCommand;
        public event deleCommandCompletedSim onCommandCompleted;
        public event deleRequestRouteSim onRequestRoute;
        public event deleReportVehicleInfoSim onReportVehicleInfo;
        public event deleReportInterlockSignalSim onReportInterlockSignal;
        public event deleOnRcvMsgSim onRcvMsg;
        public event deleOnSendMsgSim onSendMsg;
        #endregion event

        public CVehicleSimSocketDriver SimDriver;

        Thread thrdExcuteVehicleJob;

        CAGVCDB AGVCDB;

        public int ID
        {
            get;
            set;
        }

        public string Name
        {
            get;
            set;
        }

        public int PreNode
        {
            get;
            set;
        }

        public int CurNode
        {
            get;
            set;
        }

        public int NextNode
        {
            get;
            set;
        }

        public int CurAlarm
        {
            get;
            set;
        }

        public enumConnect Connect
        {
            get;
            set;
        }

        public enumCommnication Commnuication
        {
            get;
            set;
        }

        public enumContolState ControlState
        {
            get;
            set;
        }

        public enumOperation Operation
        {
            get;
            set;
        }

        public CVehicleJob CurVehicleJob
        {
            get;
            set;
        }

        public string CommType
        {
            get;
            set;
        }

        public string EjectType
        {
            get;
            set;
        }

        public string GuideType
        {
            get;
            set;
        }

        public int BatteryLowLevel
        {
            get;
            set;
        }

        public int BatteryLevel
        {
            get;
            set;
        }

        public bool CanForward
        {
            get;
            set;
        }

        public bool CanBackward
        {
            get;
            set;
        }

        public bool CanLeft
        {
            get;
            set;
        }

        public bool CanRight
        {
            get;
            set;
        }

        public bool CanSideLeft
        {
            get;
            set;
        }

        public bool CanSideRight
        {
            get;
            set;
        }

        public IPAddress AGVCIP
        {
            get;
            set;
        }

        public IPAddress VehicleIP
        {
            get;
            set;
        }

        public int Port
        {
            get;
            set;
        }

        public int MovingInterval = 3000;

        CVehicleJob curVehicleJob = null;

        Logger Log;

        public CVehicleSim(string name)
        {
            this.Name = name;

            AGVCDB = CAGVCDB.getInstance();

            thrdExcuteVehicleJob = new Thread(new ThreadStart(ExcuteVehicleJob));

            Log = new Logger(Name);
        }

        public int InitModule()
        {
            SimDriver = new CVehicleSimSocketDriver(AGVCIP, Port);

            RegisterEvent();

            thrdExcuteVehicleJob.Start();

            return CReturnCode.SUCCESS;
        }

        int GetDataFromDB()
        {
            return CReturnCode.SUCCESS;
        }

        void RegisterEvent()
        {
            SimDriver.onRcvMsg += new Driver.deleOnRcvMsg(SimDriver_onRcvMsg);
            SimDriver.onSendMsg += new Driver.deleOnSendMsg(SimDriver_onSendMsg);
            SimDriver.onConnect += new deleSocketSimOnConnect(SimDriver_onConnect);
        }

        void SimDriver_onSendMsg(object sender, string msg)
        {
            if (onSendMsg != null)
                onSendMsg(this, msg);
        }

        void SimDriver_onConnect(object sender, enumConnect connect)
        {
            if (onReportConnection != null)
                onReportConnection(this, connect);
        }

        void SimDriver_onRcvMsg(object sender, string msg)
        {
            if (onRcvMsg != null)
                onRcvMsg(this, msg);
        }

        public void ConnectAGVC()
        {
            SimDriver.Connect();
        }

        public void DisconnectAGVC()
        {
            SimDriver.Close();
        }

        public void ReportCommnication(enumCommnication value)
        {
            this.Commnuication = value;
            SimDriver.ReportCommnucation(value);
        }

        public void ReportOperation(enumOperation value)
        {
            this.Operation = value;
            SimDriver.ReportOperation(value);
        }

        public void ReportControlState(enumContolState value)
        {
            this.ControlState = value;
            SimDriver.ReportControlState(value);
        }

        public void ReportPosition(int preNodeID, int curNodeID, int nextNodeId)
        {
            SimDriver.ReportPosition(preNodeID, curNodeID, nextNodeId);
        }

        public void SendMsg(string msg)
        {
            SimDriver.Send(msg);
        }

        public void ReportAlarm(int alarmid, bool set)
        {
            SimDriver.ReportAlarm(alarmid, set);
        }

        public int SetVehicleJob(CVehicleJob vehicleJob)
        {
            if (curVehicleJob != null) return CReturnCode.ERR_VEHICLE_VEHICLEJOB_EXIST;

            curVehicleJob = vehicleJob;

            curVehicleJob.State = enumVehicleJobState.QUEUED;

            return CReturnCode.SUCCESS;
        }

        public void ExcuteVehicleJob()
        {
            while (true)
            {
                //is Exist Vehicle Job??
                if (curVehicleJob == null)
                {
                    goto JUMP;
                }

                //if exist

                //switch Action

                //Move Position
                //Excute Eject

            JUMP:
                Thread.Sleep(100);
            }
        }
    }

    public class CVehicleSimDic : Dictionary<int, CVehicleSim>
    {
        CAGVCDB AGVCDB;
        Logger Log;

        private static CVehicleSimDic uniqueInstance;

        public static CVehicleSimDic getInstance()
        {
            if (uniqueInstance == null)
            {
                uniqueInstance = new CVehicleSimDic();
            }
            return uniqueInstance;
        }

        public CVehicleSimDic()
        {
            Log = new Logger("CVehicleSim");
            AGVCDB = CAGVCDB.getInstance();

            GetDataFromDB();
        }

        //public int InitModule()
        //{
        //    int resurncode = CReturnCode.SUCCESS;

        //    foreach (KeyValuePair<int, CVehicleSim> vehicleSim in this)
        //    {
        //        resurncode = vehicleSim.Value.InitModule();
        //    }

        //    return resurncode;
        //}

        public int GetDataFromDB()
        {
            try
            {
                DataTable table = AGVCDB.AGVCDataSet.Tables["VehicleList"];
                CVehicleSim vehicleSim;

                foreach (DataRow row in table.Rows)
                {
                    vehicleSim = new CVehicleSim(Convert.ToString(row["Name"]));
                    vehicleSim.ID = Convert.ToInt32(row["ID"]);
                    vehicleSim.CommType = Convert.ToString(row["CommType"]);
                    vehicleSim.EjectType = Convert.ToString(row["EjectType"]);
                    vehicleSim.GuideType = Convert.ToString(row["GuideType"]);
                    vehicleSim.BatteryLowLevel = Convert.ToInt32(row["BatteryLowLevel"]);
                    vehicleSim.CanForward = Convert.ToBoolean(row["CanForward"]);
                    vehicleSim.CanBackward = Convert.ToBoolean(row["CanBackward"]);
                    vehicleSim.CanLeft = Convert.ToBoolean(row["CanLeft"]);
                    vehicleSim.CanRight = Convert.ToBoolean(row["CanRight"]);
                    vehicleSim.CanSideLeft = Convert.ToBoolean(row["CanSideLeft"]);
                    vehicleSim.CanSideRight = Convert.ToBoolean(row["CanSideRight"]);
                    vehicleSim.Port = Convert.ToInt32(row["Port"]);
                    vehicleSim.AGVCIP = IPAddress.Parse(Convert.ToString(row["AGVCIP"]));
                    vehicleSim.VehicleIP = IPAddress.Parse(Convert.ToString(row["VehicleIP"]));

                    vehicleSim.InitModule();

                    this.Add(vehicleSim.ID, vehicleSim);
                }
            }
            catch (Exception ex)
            {
                Log.Exception(string.Format("{0},{1}", ex.Message, ex.StackTrace));
                return CReturnCode.ERR_DATA_ACQUIRING_FAIL;
            }

            return CReturnCode.SUCCESS;
        }
    }
}
